﻿Function.prototype.method = function (name, func) {
	this.prototype[name] = func;
	return this;
};

Function.method('inherits', function (parent) {
	var d = {}, p = (this.prototype = new parent());
	this.method('uber', function uber(name) {
		if (!(name in d)) d[name] = 0;
		var f, r, t = d[name], v = parent.prototype;
		if (t) {
			while (t) {
				v = v.constructor.prototype;
				t -= 1;
			}
			f = v[name];
		} else {
			f = p[name];
			if (f == this[name]) f = v[name];
		}
		d[name] += 1;
		r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
		d[name] -= 1;
		return r;
	});
	return this;
});

function getFirstAncestorOfType(elem, type) {
	var e = elem;
	while (e!= null  && e.tagName != type) e = e.parentNode;
	return e.tagName == type ? e: null;
}

function DragAndDropHandler(elem, handler) {
	$(elem).attr('draggable', 'true');
	$(elem).dragstart(handler.dragstart);
	$(elem).dragenter(handler.dragenter);
	$(elem).dragleave(handler.dragleave);
	$(elem).dragend(handler.dragend);
	$(elem).dragover(handler.dragover);
	$(elem).drop(handler.drop);
};

function Map() {
	this.map = [];
	this.change = new EventManager();
	this.get = function(key) {
		for (var i=0;i<this.map.length;i++) if (this.map[i].key == key) return this.map[i].value;
	};
	this.put = function(key, value) {
		if (key == null) throw new Error("Cannot add a value without a key into a map object");
		var i = this.index(key);
		if (i == null) {
			this.map.push({key: key, value: value});
		} else {
			this.map[i].value = value;
		}
		this.change.trigger();
	};
	this.clear = function() {
		this.map = [];
		this.change.trigger();
	};
	this.index = function(key) {
		for (var i=0;i<this.map.length;i++) if (this.map[i].key == key) return i;
		return null;
	};
	this.contains = function(key) {
		return this.index(key) != null;
	};
	this.remove = function(key) {
		this.map.splice(this.index(key), 1);
		this.change.trigger();
	};
	this.getKeyByValue = function(value) {
		for (var i=0;i<this.map.length;i++) if (this.map[i].value == value) return this.map[i].key;
	};
	this.getKeys = function() {
		var keys = [];
		for (var i=0;i<this.map.length;i++) keys.push(this.map[i].key);
		return keys;
	};
	this.values = function() {
		var values = [];
		for (var i=0;i<this.map.length;i++) values.push(this.map[i].value);
		return values;
	};
	this.getKeyByIndex = function(i) {
		return this.map[i].key;
	};
	this.size = function() {
		return this.map.length;
	};
}

function EventManager() {
	this.listeners = [];
	this.add = function(listener) {
		if($.inArray(listener, this.listeners) == -1) {
			this.listeners.push(listener);
		}
	};
	this.remove = function(listener) {
		this.listeners.splice(this.index(listener), 1);
	};
	this.index = function(key) {
		for (var i=0;i<this.listeners.length;i++) {
			if (this.listeners[i] == key) return i;
		}
		return null;
	};
	this.trigger = function(args) {
		for (var i=0;i<this.listeners.length;i++) this.listeners[i](args);
	};
}